package handler

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"math/rand"
	"net/http"
	"rbook/api/request"
	"rbook/consts"
	"rbook/globals"
	"rbook/intermal/model"
	"rbook/pkg"
	"regexp"
	"strconv"
	"time"
)

// 设置短信验证码入参
var sends request.SendSms

// 设置手机号正则
var phoneRegexp = regexp.MustCompile(`^1[3-9]\d{9}$`)

// 设置手机号码正则验证码实现的方法
func IsVal(phone string) bool {
	return phoneRegexp.MatchString(phone)
}

// 设置短信验证码的接口
type Work interface {
	Work1() int
}

// 设置短信验证码结构体
type One struct {
	Phone string
}

// 实现结构体方法
func (y *One) Work1() int {
	//设置四位随机数字
	i := rand.Intn(9000) + 1000
	//调用pkg方法
	pkg.SendSms(sends.Phone, strconv.Itoa(i))
	//返回类型
	return i
}

// 实现结构体方法 用swich
func Send(demo string) *One {
	switch demo {
	case "A":
		return &One{Phone: sends.Phone}

	}
	return nil
}

// 短信验证码接口
func SendSms(c *gin.Context) {
	//判断入参是否错误
	if err := c.ShouldBind(&sends); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "参数错误",
		})
		return
	}
	//调用方法 实现验证码
	work := Send("A")
	code := work.Work1()
	CodeStr := strconv.Itoa(code)

	if !IsVal(sends.Phone) {
		c.JSON(http.StatusOK, gin.H{
			"mes": "当前手机号码格式错误",
		})
		return
	}

	val := globals.RDB.Get(globals.Ctx, "sendCode"+sends.Phone).Val()
	if val >= "1" {
		c.JSON(http.StatusOK, gin.H{
			"mes": "当前短信只能一分钟发送一次",
		})
		return
	}
	//使用redis缓存 把验证码存进去
	err := globals.RDB.Set(globals.Ctx, "sendSms"+sends.Phone, CodeStr, time.Minute*5).Err()
	//返回错误
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "短信验证码发送错误",
		})
		return
	}
	incr := globals.RDB.Incr(globals.Ctx, "sendCode"+sends.Phone).Val()
	if incr == 1 {
		globals.RDB.Expire(globals.Ctx, "sendCode"+sends.Phone, time.Minute*1)
	}
	//返回正确
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"mes":  "短信验证码发送成功",
	})
}

func Login(c *gin.Context) {
	param := request.Login{}
	if err := c.ShouldBind(&param); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "参数错误",
		})
		return
	}
	data := model.User{}
	//判断用户是否存在
	globals.DB.Where("phone=?", param.Phone).Find(&data)
	if data.Id == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "该用户不存在,请先去注册",
		})
		return
	}
	//判断验证码是否失效
	result, _ := globals.RDB.Get(globals.Ctx, "sendSms"+param.Phone).Result()
	if result != param.SendCode {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "验证码已失效",
		})
		return
	}
	token := pkg.Token(uint(data.Id), time.Hour*2, consts.JWT_KEY)
	marshal, err := json.Marshal(&data)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "序列化失败",
		})
		return
	}
	err = globals.RDB.Set(globals.Ctx, "token", marshal, time.Hour*2).Err()
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "登录凭证存储在缓存中失败",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"mes":  "登陆成功",
		"data": map[string]interface{}{
			"data":       data.Id,
			"token":      token,
			"login_time": time.Now(),
		},
	})
}

var user []model.User

func Time(c *gin.Context) {
	var count = 0
	var count1 = 0
	time.AfterFunc(time.Second*5, func() {
		globals.DB.Where("last_login_time<=?", time.Now().AddDate(0, 0, 1)).Find(&user)
		fmt.Println("定时任务开启", time.Now().Format("2006-01-01"))
		for i := 0; i < len(user); i++ {
			count++
		}

		globals.DB.Where("last_login_time<=?", time.Now().AddDate(0, 0, 1)).Find(&user)
		fmt.Println("定时任务开启", time.Now().Format("2006-01-01"))
		for i := 0; i < len(user); i++ {
			count1++
		}
		number := &model.Number{
			RegisterTime: int32(count),
			LoginTime:    int32(count1),
		}
		globals.DB.Create(&number)
	})
}

func UserDetails(c *gin.Context) {
	param := request.UserDetails{}
	if err := c.ShouldBind(&param); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": 400,
			"mes":  "参数错误",
		})
		return
	}
	data := model.User{
		Id: int32(param.Id),
	}
	globals.DB.Model(model.User{}).Where("id=?", data.Id).Find(&data)
	//关注数
	var followerCount int64
	globals.DB.Model(model.Follow{}).Where("follower_id=?", param.Id).Count(&followerCount)
	//粉丝数
	var followedCount int64
	globals.DB.Model(model.Follow{}).Where("followed_id=?", param.Id).Count(&followedCount)

	result, err := globals.RDB.Get(globals.Ctx, "user_details").Result()
	if result != "" {
		err = json.Unmarshal([]byte(result), &data.AvatarUrl)
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"mes": "序列化失败",
			})
		}
	} else {
		marshal, _ := json.Marshal(&data.AvatarUrl)
		globals.RDB.Set(globals.Ctx, "user_details", marshal, time.Hour*1)
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"mes":  "个人详情展示成功",
		"data": map[string]interface{}{
			"url":       data.AvatarUrl,
			"nick_name": data.Nickename,
			"region":    data.Region,
			"follower":  followerCount,
			"followed":  followedCount,
		},
	})
}
